package dataStructures.list;

/**
 * 
 * Fully Tested: Yes
 * Fully Documented: Yes
 * Created: 2011
 * Last Modified: Nov 9, 2011
 * 
 * @author Shimu
 */
public class Queue<T> {

    /** The size of the Queue */
    private int size;

    /** A pointer to the first and last item in the queue */
    private SinglelyLinkedNode<T> first, last;

    /** 
     * Instantiates an empty Queue.
     */
    public Queue() {
        this.size = 0;
        this.first = null;
        this.last = null;
    }

    /**
     * Instantiates a Queue containing only the given data.
     * 
     * @param firstData the first and only item in the new Queue
     */
    public Queue(T firstData){
        this();
        enqueue(firstData);
    }

    /**
     * Adds an item to the back of the queue.
     * @param data the item to be added
     */
    public final void enqueue(T data) {
        SinglelyLinkedNode newNode = new SinglelyLinkedNode(data);
        if (first == null) {
            first = newNode;
            first.next = last;
        } else if (last == null) {            
            last = newNode;
            first.next = last;
        } else {
            last.next = newNode;
            last = last.next;
        }
        size++;
    }

    /**
    public void enqueueAll(Queue<T> otherQueue) {
        
    }*/
    
    /**
     * Returns and removes the item at the front of the queue.
     * 
     * @return the item at the front of the queue.
     */
    public T dequeue() {
        if (first == null) {
            return null;
        } else {
            T returnData = first.data;
            first = first.next;
            size--;
            return returnData;
        }
    }

    
    /**
     * Returns true if this Queue has no more elements, false otherwise.
     * @return true if this Queue is empty.
     */
    public boolean isEmpty() {
        return (size == 0);
    }

    /**
     * Returns the number of elements in this Queue.
     * @return the size of this Queue.
     */
    public int getSize() {
        return this.size;
    }
}
